import rxAjax from '@/assets/js/ajax.js';
import { Util,IndexedDb,TokenUtil } from '@lowcode/jpaas-common-lib'
import store from '@/store';
import {
    UrlView,
    MainLayout,
    InnerLayout
} from '@/layouts'



// 前端路由表,等于公共模块
const constantRouterComponents = {
    UrlView: UrlView,
    MainLayout: MainLayout
}

// 前端未找到页面路由（固定不用改）
const notFoundRouter = {
    path: '*', redirect: '/404', hidden: true
}


/**
 * 获取后端用户与路由菜单信息
 */
export const getLoginUserAndMenu = () => {
    let url = "/api-user/user/org/osUser/getLoginUserAndMenu";
    return rxAjax.get(url);
}



/**
 * 获取用户与路由菜单信息
 * @returns {Promise<any>}
 */
export const generatorDynamicRouter = () => {
    return new Promise((resolve, reject) => {
        getLoginUserAndMenu().then(res => {
            //设置首次登录状态
            let firstLogin=res.data.user.isFirstLogin == "YES";
            store.state.appSetting.isFirstLogin = firstLogin;
            var data = res.data.menus;
            var menuMap = {};
            for (var i = 0; i < data.length; i++) {
                menuMap[data[i].id] = data[i]
            }
            const result = buildmenu(data, res.data.user);
            const allRouters = buildAllRouter(data, res.data.user);
            const i18nMenuJson = buildI18nmenu(result);
            const routers = constructRouters(allRouters);
            callBackMenus(result);
            const appKeys = getAppList(data);
            const buttons = getButtons(data, appKeys);
            const appMode= res.data.appMode;
            var json = {
                menus: result,
                i18nMenuJson:i18nMenuJson,
                routers: routers,
                menuMap: menuMap,
                buttons: buttons,
                user: res.data.user,
                allButtons: res.data.allMenuButtons,
                appMode:appMode
            };
            initIndexedDb(res.data.user);
            resolve(json);
        }).catch(err => {
            reject(err);
        })
    })
}

const  CUR_LOGIN_USER_DB="CUR_LOGIN_USER_DB";
const  CUR_LOGIN_USER="CUR_LOGIN_USER";
const  CUR_LOGIN_USER_KEY="curUserKey";
function initIndexedDb(user) {
    /*
     *打开数据库
     */
    IndexedDb && IndexedDb.initDataBase(CUR_LOGIN_USER_DB,CUR_LOGIN_USER,CUR_LOGIN_USER_KEY).then(()=>{
        setTimeout(function (){
            initUserToIndexedDb(user);
        }, 5000);
    });

}
async function initUserToIndexedDb(user) {
    /*
     *取到当前缓存：
    * 1、如果有数据就更新，没数据就新增
    */
    user.curUserKey=CUR_LOGIN_USER_KEY+"userJson";
    let res =await  IndexedDb.getByKey(CUR_LOGIN_USER,CUR_LOGIN_USER_KEY);
    if(!res.success){
        IndexedDb.insert(CUR_LOGIN_USER, user);
    }else {
        IndexedDb.update(CUR_LOGIN_USER, user);
    }
    IndexedDb.close();
}


function getButtons(data, appKeys) {
    if (!data || data.length == 0) {
        return appKeys;
    }
    data.forEach(item => {
        if (item.menuType === "F") {
            var appId = item.appId;
            var appKey = getAppKey(appId, data);
            if (typeof (appKeys[appKey]) == 'undefined') {
                appKeys[appKey] = [];
                appKeys[appKey].push(item.menuKey);
            } else {
                appKeys[appKey].push(item.menuKey);
            }
        }
    });
    return appKeys;
}

/**
 * 获取应用Key
 * @param appId
 * @param data
 * @returns {default.methods.key}
 */
function getAppKey(appId, data) {
    let app = data.find(item => item.menuType === "C" && appId === item.id);
    if (app) {
        return app.menuKey;
    } else {
        return "";
    }
}


function getAppList(data) {
    var appKeys = {};
    if (!data || data.length == 0) {
        return appKeys;
    }
    data.forEach(item => {
        if (item.menuType === "C" && item.appId === item.id) {
            appKeys[item.menuKey] = [];
        }
    });
    return appKeys;
}
function setNewPage(data){//设置新页面（vue文件）的路由
    let _data = Util.deepClone(data)
    let arr = [];
    let filters = (item) =>{
        if(!item){ return }
        for (let i = 0 ;i < item.length ;i++){
            let menu = item[i] ;
            if(menu.showType == 'NEW_PAGE'){
                let component = loadView(menu.component);
                let router = {
                    name: menu.key,
                    path: "/" + menu.key,
                    component: component,
                    props:true,
                    meta: {
                        menuType: menu.menuType,
                        params: menu.params,
                        id: menu.id
                    }
                }
                arr.push(router);
            }
            if(menu.children){
                filters(menu.children);
            }
        }
    }
    filters(_data.children);
    return arr;
}
/**
 * 构建路由。
 * @param menus
 * @returns {[]}
 */
function constructRouters(menus) {
    let layoutObj = {
        MainLayout:MainLayout,
        InnerLayout:InnerLayout,
    }
    let ary = [];
    for (let i = 0; i < menus.length; i++) {
        let menu = menus[i];
        if (menu.appType == '1' && menu.menuNavType == '1') {
            delete menu.children;
        }
        let rootPath = "/" + menu.key;

        let parentModule = menu.parentModule?layoutObj[menu.parentModule] : MainLayout ;

        let parentRouter = {id: menu.id, name: menu.key + "Home", path: menu.layout=='many'?rootPath + '/home':'', component: parentModule};
        let routers = [];
        let component = getComponent(menu);
        let router = {
            name: menu.key,
            path: rootPath,
            component: component,
            meta: {
                menuType: menu.menuType,
                params: menu.params,
                id: menu.id
            }
        };
        let newPage =  setNewPage(menu);
        ary = [...ary,...newPage];
        routers.push(router);
        buildRouters(menu, routers);
        parentRouter.children = routers;
        ary.push(parentRouter);
    }
    return ary;
}

/**
 * 获取插件。
 * @param menu
 * @returns {{data, watch, created, methods, name}}
 */
export function getComponent(menu) {
    var obj = null;
    if (!menu.settingType || menu.settingType == "iframe") {
        obj = UrlView;
    } else {
        if (menu.component) {
            if (typeof menu.component === "function") {
                obj = menu.component;
            } else {
                obj = loadView(menu.component);
            }
        }
    }
    return obj;
}

function buildRouters(parent, routers) {
    if (!parent.children) {
        return;
    }
    for (var i = 0; i < parent.children.length; i++) {
        var menu = parent.children[i];
        var path = (parent.path || "") + (parent.path ? "/" : "") + menu.key;
        menu.path = path;
        if (menu.showType == 'NEW_PAGE') {//新页面（vue文件）的时候 直接跳过；
            continue ;
        }
        if (menu.menuType == 'C' || menu.menuType == 'R') {
            var component = getComponent(menu);
            //判断是否需要拼接token url最后为&accessToken结尾则拼接token
            if (menu.params && typeof (menu.params) == 'string') {
                var str = menu.params.substring(menu.params.indexOf("&"));
                if (str == "&accessToken") {
                    var accessToken = TokenUtil.getToken();
                    if (accessToken) {
                        menu.params = menu.params + "=" + accessToken;
                    }
                }
            }
            var router = {
                name: menu.key,
                path: path,
                component: component,
                meta: {
                    menuType: menu.menuType,
                    params: menu.params,
                    id: menu.id
                }
            };
            routers.push(router);
        }
        buildRouters(menu, routers)
    }
}


export const loadView = (view) => { // 路由懒加载
    return () => import(`@/views/${view}`)
}

/**
 * 构建菜单。
 * @param rows
 * @returns {[]}
 */
export function buildmenu(rows, user) {
    var newRows = [];
    rows.forEach(item => {
        // 菜单不需要显示路由类型的，把R类型也排除掉。
        if (item.menuType != "F" && item.menuType != "I"  && item.menuType != "R") {
            newRows.push(item);
        }
    });

    const menus = [];
    buildtree(newRows, menus, '0', user);
    for (var i = 0; i < menus.length; i++) {
        if (menus[i].children) {
            menus[i].children.sort(compareSn('sn'));
        }
    }


    return menus;
}

/**
 * 构建路由。
 * @param rows
 * @returns {[]}
 */
export function buildAllRouter(rows, user) {
    var newRouters = [];
    rows.forEach(item => {
        // 路由需要显示路由类型的，不排除
        if (item.menuType != "F" && item.menuType != "I" ) {
            newRouters.push(item);
        }
    });
    const routers = [];
    buildtree(newRouters, routers, '0', user);
    for (var i = 0; i < routers.length; i++) {
        if (routers[i].children) {
            routers[i].children.sort(compareSn('sn'));
        }
    }

    return routers;
}


/**
 * 构建i18n菜单。
 * @param rows
 * @returns {[]}
 */
export function buildI18nmenu(rows) {
    let i18nList=[];
    let i18nStr=window.localStorage.getItem("i18nList");
    if(i18nStr){
        i18nList=JSON.parse(i18nStr);
    }

    const i18nMenuJson ={};
    for (var i = 0; i < i18nList.length; i++) {
        let i18n=i18nList[i];
        rows.forEach(item => {
            let menu={
                key:"systemMenus."+item.key,
                title:getI18nNameByType(i18n.type,item.title)
            };
            if(item.children && item.children.length>0){
                for (var k = 0; k < item.children.length; k++) {
                    buildSunI18nmenu(menu,i18n.type,item.children[k]);
                }
            }
            i18nMenuJson[i18n.type]=menu;
        });
    }
    return i18nMenuJson;
}

export function buildSunI18nmenu(parentMenu,type,item) {
    let menu={
        key:parentMenu.key+"."+item.key,
        title:getI18nNameByType(type,item.title)
    };
    if(item.children && item.children.length>0){
        for (var k = 0; k < item.children.length; k++) {
            buildSunI18nmenu(menu,type,item.children[k]);
        }
    }
    parentMenu[item.key]=menu;
}

export function getI18nNameByType(type,name) {
    let val="";
    try {
        let jsonName=JSON.parse(name);
        val=jsonName[type];
        if(!val){
            val=name;
        }
    }catch (e) {
        val=name;
    }
    return val;
}

/**
 * 递归构建菜单。
 * @param list
 * @param arr
 * @param parentId
 */
export function buildI18ntree(type,list, arr, parentId, user, appType, menuNavType) {
    list.forEach(item => {
        if (item.parentId === parentId) {
            if (item.instConfig) {
                let insConfig=item.instConfig.trim();
                if(insConfig.startsWith("{") ){
                    var instConfigs = JSON.parse(insConfig);
                    for (let i = 0; i < instConfigs.length; i++) {
                        if (instConfigs[i].instLabel == user.tenantLabel) {
                            item.component = instConfigs[i].component;
                            item.params = instConfigs[i].params;
                        }
                    }
                }
            }
            var child = {
                title: item.name,
                key: item.menuKey,
                id: item.id,
                sn: item.sn,
                icon: item.iconPc,
                showType: item.showType,
                menuType: item.menuType,
                settingType: item.settingType,
                component: item.component,
                layout: item.layout,
                parentModule: item.parentModule,
                params: item.params,
                children: [],
                appType: item.appType || appType,
                appPath: item.appPath,
                menuNavType:menuNavType || item.menuNavType ,
                backColor: item.backColor,
                isFav: item.isFav,
                lastUseTime: item.lastUseTime,
                appId: item.appId,
                categoryId: item.categoryId,
                navType:item.navType
            }
            buildI18ntree(type,list, child.children, item.id, user, child.appType, child.menuNavType);
            if (child.children.length === 0) {
                delete child.children
            }
            arr.push(child)
        }
    })
}

function compareSn(property) {
    return function (obj, obj2) {
        return obj[property] - obj2[property]
    }
}

/**
 * 解析目录打开方式
 * @param menus
 */
export function callBackMenus(menus) {
    for (let i = 0; i < menus.length; i++) {
        var showType = menus[i].showType;
        if (!menus[i].children || menus[i].children.length == 0) continue;
        callBackMenus(menus[i].children);
    }
}

/**
 * 递归构建菜单。
 * @param list
 * @param arr
 * @param parentId
 */
export function buildtree(list, arr, parentId, user, appType, menuNavType) {
    list.forEach(item => {
        if (item.parentId === parentId) {
            if (item.instConfig) {
                let insConfig=item.instConfig.trim();
                if(insConfig.startsWith("{") ){
                    var instConfigs = JSON.parse(insConfig);
                    for (let i = 0; i < instConfigs.length; i++) {
                        if (instConfigs[i].instLabel == user.tenantLabel) {
                            item.component = instConfigs[i].component;
                            item.params = instConfigs[i].params;
                        }
                    }
                }
            }
            var child = {
                title: item.name,
                remarks: item.remarks,
                key: item.menuKey,
                id: item.id,
                sn: item.sn,
                icon: item.iconPc,
                showType: item.showType,
                menuType: item.menuType,
                settingType: item.settingType,
                component: item.component,
                layout: item.layout,
                parentModule: item.parentModule,
                params: item.params,
                children: [],
                appType: item.appType || appType,
                appPath: item.appPath,
                menuNavType:menuNavType || item.menuNavType ,
                backColor: item.backColor,
                isFav: item.isFav,
                lastUseTime: item.lastUseTime,
                appId: item.appId,
                categoryId: item.categoryId,
                navType:item.navType,
                isApp:item.isApp
            }
            buildtree(list, child.children, item.id, user, child.appType, child.menuNavType);
            if (child.children.length === 0) {
                delete child.children
            }
            arr.push(child)
        }
    })
}

/**
 * 根据ID取得上级对象树数据。
 * @param obj
 * @param id
 * @returns {[*]|*}
 */
export const getParentNode = (obj, id) => {
    let getParent = (list, id) => {
        for (let i in list) {
            if (list[i].id == id) {
                return [list[i]]
            }
            if (list[i].children) {
                let node = getParent(list[i].children, id);
                if (node !== undefined) {
                    return node.concat(list[i])
                }
            }
        }
    }
    return getParent(obj, id)
}
export const getParentPath = (obj, id) => {
    let getParent = (list, id) => {
        for (let i in list) {
            if (list[i].meta && list[i].meta.id == id) {
                return [list[i]]
            }
            if (list[i].children) {
                let node = getParent(list[i].children, id);
                if (node !== undefined) {
                    return node.concat(list[i])
                }
            }
        }
    }
    return getParent(obj, id)
}

export function getSelectMenus(menus, menuId) {
    var selectMenus = [];
    for (var i = 0; i < menus.length; i++) {
        if (menus[i].id == menuId) {
            selectMenus = menus[i].children;
            break;
        } else {
            if (menus[i].children && menus[i].children.length > 0) {
                var res = getSelectMenus(menus[i].children, menuId);
                if (res && res.length > 0) {
                    selectMenus = res;
                    break;
                }
            }
        }
    }
    return selectMenus;
}

/**
 * 根据key找到菜单。
 * @param key
 * @param menus
 */
export function getMenuByKey(key,menus){

    let getMenu=function (key,menus){
        var menu;
        for (let i = 0; i <menus.length ; i++) {
            let item=menus[i];
            if(item.key==key){
                menu=item;
                break;
            }else {
                if(item.children&&item.children.length>0){
                    menu=getMenu(key,item.children);
                    if(menu) break;
                }
            }
        }
        return menu;
    }
    let menu=getMenu(key,menus);

    return menu;
}
